package com.eastfair.builder.service.impl;

import cn.hutool.core.util.StrUtil;
import com.eastfair.builder.dto.ActorInfoDTO;
import com.eastfair.builder.service.MeetActorService;
import com.eastfair.builder.vo.ActorInfo;
import com.eastfair.core.exception.BizException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 厦门会议系统 service.
 *
 * @author dqq
 * @date 2023 /2/13
 */
@Service
@Slf4j
public class MeetActorServiceImpl implements MeetActorService {

    @Value("${xmmeet.properties.host}")
    private String meetHost;

    @Value("${xmmeet.properties.get-actor-info-by-build-invite-code}")
    private String getActorInfoByBuildInviteCodeUrl;

    @Value("${xmmeet.properties.get-token}")
    private String getTokenUrl;

    @Value("${xmmeet.properties.login-name}")
    private String loginName;

    @Value("${xmmeet.properties.login-pwd}")
    private String loginPwd;

    @Resource
    private RestTemplate restTemplate;

    @Override
    public String getToken() throws Exception {
        log.info("getToken - 获取展商系统token");
        String url = meetHost + getTokenUrl;
        Map<String, String> body = new HashMap<>(16);
        body.put("LoginName", loginName);
        body.put("LoginPwd", loginPwd);
        HttpEntity<Map<String, String>> httpEntity = new HttpEntity<>(body);

        log.info("getToken - 调用展商系统获取token接口, url={}, body={}", url, body);
        String result = restTemplate.postForObject(url, httpEntity, String.class);
        log.info("getToken - 调用展商系统获取token接口完成, result={}", result);

        ObjectMapper objectMapper = new ObjectMapper();
        ArrayNode arrayNode = (ArrayNode) objectMapper.readTree(result);
        if (arrayNode != null && !arrayNode.isEmpty()) {
            JsonNode jsonNode = arrayNode.get(0);
            JsonNode tokenJsonNode = jsonNode.get("token");
            if (tokenJsonNode.isTextual()) {
                return tokenJsonNode.asText();
            }
        }
        return null;
    }

    @Override
    public List<ActorInfo> getActorInfoByBuildInviteCode(ActorInfoDTO actorInfoDTO) throws Exception {
        log.info("getActorInfoByBuildInviteCode - 根据邀请码获取展商数据, actorInfoDTO={}", actorInfoDTO);
        String token = getToken();
        if (StrUtil.isBlank(token)) {
            throw BizException.wrap(-1, "获取展商会议系统token失败");
        }
        String url = meetHost + getActorInfoByBuildInviteCodeUrl;
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        httpHeaders.add("token", token);
        HttpEntity<ActorInfoDTO> httpEntity = new HttpEntity<>(actorInfoDTO, httpHeaders);

        log.info("getActorInfoByBuildInviteCode - 调用展商会议系统根据邀请码获取展商数据接口, url={}, httpEntity={}", url, httpEntity);
        String result = restTemplate.postForObject(url, httpEntity, String.class);
        log.info("getActorInfoByBuildInviteCode - 调用展商会议系统根据邀请码获取展商数据接口完成, result={}", result);

        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode resultJsonNode = objectMapper.readTree(result);
        JsonNode codeJsonNode = resultJsonNode.get("code");
        if (codeJsonNode.isNull() || !codeJsonNode.isTextual() || !"200".equals(codeJsonNode.asText())) {
            throw BizException.wrap(-1, "调用展商会议系统根据邀请码获取展商数据接口错误");
        }
        JsonNode dataJsonNode = resultJsonNode.get("data");
        if (!dataJsonNode.isNull() && dataJsonNode.isArray()) {
            return objectMapper.convertValue(dataJsonNode, new TypeReference<List<ActorInfo>>(){});
        }
        return null;
    }
}